package com.example.demo.use_demo.a_rrate_limiter;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

@Aspect
@Component
@Slf4j
public class PersonModifyLimitAdvice implements CommandLineRunner {

    // 令牌间隔生成数
    private static final int RATE = 1;
    // 令牌生成间隔时间
    private static final int RATE_INTERVAL = 5;

    @Autowired
    private RedissonClient redisson;

    private RRateLimiter rRateLimiter;

    @Around(value = "@annotation(apiLimit)")
    public Object around(ProceedingJoinPoint pjp, PersonModifyLimit apiLimit) throws Throwable {
        int waitingTime = apiLimit.waitingTime();
        int permits = apiLimit.permits();
        TimeUnit timeUnit = apiLimit.timeUnit();
        boolean isPass = waitingTime == 0 ? rRateLimiter.tryAcquire(permits) : rRateLimiter.tryAcquire(permits,waitingTime,timeUnit);
        if(isPass){
            return pjp.proceed();
        } else {
            throw new RuntimeException("请稍后再试~");
        }
    }

    @Override
    public void run(String... args) throws Exception {
        // 创建一个限流器
        this.rRateLimiter = redisson.getRateLimiter("PersonModifyLimit");
        // 删除原有配置
        this.rRateLimiter.delete();
        // 每 RATE_INTERVAL 秒钟产生 RATE 个令牌
        this.rRateLimiter.trySetRate(RateType.OVERALL, RATE, RATE_INTERVAL, RateIntervalUnit.SECONDS);
        // 打印配置
        RateLimiterConfig config = this.rRateLimiter.getConfig();
        log.info("PersonModifyLimit Config : rate:{} rateInterval:{} rateType:{}",config.getRate(),config.getRateInterval(),config.getRateType());
    }
}
